﻿using System;
using System.Collections.Generic;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
using YArchitech.Revit;
using YArchitech.Revit.Electric.Common;

namespace Model
{
	public class RoundBeanEntity
	{
		public static bool ConfirmRefMEPCurveSize(CableTrayConduitBase cableTray, MEPCurve mepCurve)
		{
			XYZ basisZ = RoundBeanEntity.GetMEPCurveConn(cableTray).CoordinateSystem.BasisZ;
			XYZ basisX = RoundBeanEntity.GetMEPCurveConn(mepCurve).CoordinateSystem.BasisX;
			return basisZ.IsAlmostEqualTo(basisX) || basisZ.IsAlmostEqualTo(-basisX);
		}

		private static Connector GetMEPCurveConn(MEPCurve cableTray)
		{
			Connector result = null;
			ConnectorSetIterator connectorSetIterator = cableTray.ConnectorManager.Connectors.ForwardIterator();
			if (connectorSetIterator.MoveNext())
			{
				result = (connectorSetIterator.Current as Connector);
			}
			return result;
		}

		public static double GetLeastOffset(Document doc, CableTrayConduitBase ct, RoundBeamType type, double angle)
		{
			double result = 0.0;
			try
			{
				CableTrayConduitBase cableTrayConduitBase = null;
				double num = AssistFunc.mmToFeet(2000.0);
				ElementId elementId = ct.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM).AsElementId();
				ElementId id = (doc.GetElement(ct.GetTypeId()) as MEPCurveType).Id;
				HYCableTray<CableTrayConduitBase> hycableTray = new HYCableTray<CableTrayConduitBase>(ct);
				XYZ startXYZ = hycableTray.StartXYZ;
				XYZ endXYZ = hycableTray.EndXYZ;
				CableTrayConduitBase cableTrayConduitBase2;
				if (ct is Conduit)
				{
					cableTrayConduitBase2 = Conduit.Create(doc, id, new XYZ(0.0, 0.0, 0.0), new XYZ(10.0, 0.0, 0.0), elementId);
				}
				else
				{
					cableTrayConduitBase2 = CableTray.Create(doc, id, new XYZ(0.0, 0.0, 0.0), new XYZ(10.0, 0.0, 0.0), elementId);
				}
				RoundBeanEntity.ParameterConvert(ct, cableTrayConduitBase2, doc);
				HYCableTray<CableTrayConduitBase> hycableTray2 = new HYCableTray<CableTrayConduitBase>(cableTrayConduitBase2);
				startXYZ = hycableTray2.StartXYZ;
				endXYZ = hycableTray2.EndXYZ;
				XYZ xyz = (endXYZ - startXYZ).Normalize();
				double num2 = Math.Tan(angle);
				if (num2 < 0.0001)
				{
					num2 = 0.0;
				}
				double num3 = 0.0;
				if (0.0 != num2)
				{
					num3 = Math.Abs(num / num2);
				}
				if (Math.Abs(num3) < 0.0001)
				{
					num3 = 0.0;
				}
				if (type == RoundBeamType.Lift)
				{
					XYZ xyz2 = endXYZ + xyz * num3 + num * XYZ.BasisZ;
					if (ct is Conduit)
					{
						cableTrayConduitBase = Conduit.Create(doc, id, endXYZ, xyz2, elementId);
					}
					else
					{
						cableTrayConduitBase = CableTray.Create(doc, id, endXYZ, xyz2, elementId);
					}
					RoundBeanEntity.ParameterConvert(ct, cableTrayConduitBase, doc);
				}
				else if (type == RoundBeamType.Offset)
				{
					CableTrayConduitBase cableTrayConduitBase3;
					if (ct is Conduit)
					{
						cableTrayConduitBase3 = Conduit.Create(doc, id, startXYZ, endXYZ, elementId);
					}
					else
					{
						cableTrayConduitBase3 = CableTray.Create(doc, id, startXYZ, endXYZ, elementId);
					}
					RoundBeanEntity.ParameterConvert(ct, cableTrayConduitBase3, doc);
					ElementTransformUtils.RotateElement(doc, cableTrayConduitBase3.Id, Line.CreateBound(startXYZ, new XYZ(startXYZ.X, startXYZ.Y, startXYZ.Z + 100.0)), Math.PI*.5);
					Line curve = (cableTrayConduitBase3.Location as LocationCurve).Curve as Line;
					XYZ xyz3 = (curve.GetEndPoint(1) - curve.GetEndPoint(0)).Normalize();
					XYZ xyz4 = endXYZ + xyz * num3 + num * xyz3;
					if (ct is Conduit)
					{
						cableTrayConduitBase = Conduit.Create(doc, id, endXYZ, xyz4, elementId);
					}
					else
					{
						cableTrayConduitBase = CableTray.Create(doc, id, endXYZ, xyz4, elementId);
					}
					RoundBeanEntity.ParameterConvert(ct, cableTrayConduitBase, doc);
					doc.DeleteElement(cableTrayConduitBase3);
				}
				if (type == RoundBeamType.Lift)
				{
					RoundBeanEntity.RotateTray(cableTrayConduitBase2, cableTrayConduitBase);
				}
				IList<Connector> appropriateConnector = new HYCableTray<CableTrayConduitBase>(cableTrayConduitBase).GetAppropriateConnector(cableTrayConduitBase2);
				FamilyInstance familyInstance = doc.Create.NewElbowFitting(appropriateConnector[0], appropriateConnector[1]);
				doc.Regenerate();
				List<Connector> conduitFittingConnectors = RevitUtils.GetConduitFittingConnectors(familyInstance);
				Connector connector;
				if (appropriateConnector[0].Origin.DistanceTo(conduitFittingConnectors[0].Origin) < appropriateConnector[0].Origin.DistanceTo(conduitFittingConnectors[1].Origin))
				{
					connector = conduitFittingConnectors[0];
				}
				else
				{
					connector = conduitFittingConnectors[1];
				}
				double num4 = new HYCableTray<CableTrayConduitBase>(cableTrayConduitBase2).GetLineProject(connector.Origin).DistanceTo(connector.Origin);
				double heightOrDiameter = RoundBeanEntity.GetHeightOrDiameter(cableTrayConduitBase2);
				if (num4 < heightOrDiameter / 2.0)
				{
					result = heightOrDiameter;
				}
				else
				{
					result = num4 * 2.0;
				}
				doc.DeleteElement(cableTrayConduitBase2);
				doc.DeleteElement(familyInstance);
				doc.DeleteElement(cableTrayConduitBase);
				doc.Regenerate();
			}
			catch (Exception)
			{
			}
			return result;
		}

		private static void ParameterConvert(CableTrayConduitBase sourceCableTray, CableTrayConduitBase newCableTray, Document document)
		{
			SubTransaction subTransaction = new SubTransaction(document);
			subTransaction.Start();
			foreach (object obj in newCableTray.Parameters)
			{
				Parameter parameter = (Parameter)obj;
                switch ((int)parameter.StorageType)
				{
				case 1:
					if (!parameter.IsReadOnly)
					{
						parameter.Set(sourceCableTray.get_Parameter(parameter.Definition).AsInteger());
					}
					break;
				case 2:
					if (parameter.Id.IntegerValue != -1114132 && !parameter.IsReadOnly)
					{
						parameter.Set(sourceCableTray.get_Parameter(parameter.Definition).AsDouble());
					}
					break;
				case 3:
					if (!parameter.IsReadOnly && parameter.IsShared)
					{
						parameter.Set(sourceCableTray.get_Parameter(parameter.Definition).AsString());
					}
					break;
				case 4:
					parameter.AsElementId();
					if (!parameter.IsReadOnly)
					{
						parameter.Set(sourceCableTray.get_Parameter(parameter.Definition).AsElementId());
					}
					break;
				}
			}
            if ((int)subTransaction.Commit() == 5)
			{
				subTransaction.RollBack();
			}
		}

		public static double GetElbowFittingLeastHeight(CableTray cableTray, FamilyInstance fitting)
		{
			XYZ xyz = null;
			HYCableTray<CableTray> hycableTray = new HYCableTray<CableTray>(cableTray);
			XYZ xyz2 = (hycableTray.EndXYZ - hycableTray.StartXYZ).Normalize();
			foreach (Connector connector in RevitUtils.GetConduitFittingConnectors(fitting))
			{
				if (!connector.CoordinateSystem.BasisZ.IsAlmostEqualTo(xyz2))
				{
					xyz = connector.Origin;
					break;
				}
			}
			return xyz.DistanceTo(hycableTray.GetLineProject(xyz));
		}

		private static void RotateTray(CableTrayConduitBase cableTray, CableTrayConduitBase refCableTray)
		{
			HYCableTray<CableTrayConduitBase> hycableTray = new HYCableTray<CableTrayConduitBase>(cableTray);
			HYCableTray<CableTrayConduitBase> hycableTray2 = new HYCableTray<CableTrayConduitBase>(refCableTray);
			Transform coordinateSystem = hycableTray.CustomConnectorStart.Connector.CoordinateSystem;
			double num = hycableTray2.CustomConnectorStart.Connector.CoordinateSystem.BasisX.AngleOnPlaneTo(coordinateSystem.BasisX, XYZ.BasisZ);
			if (num >= Math.PI)
			{
				num -= Math.PI;
			}
			if (num != 0.0)
			{
				Line line = Line.CreateUnbound(hycableTray2.StartXYZ, XYZ.BasisZ);
				hycableTray2.CableTray.Location.Rotate(line, num);
			}
		}

		public static double GetHeightOrDiameter(MEPCurve mepCurve)
		{
			double result = 0.0;
			if (mepCurve is Duct)
			{
				if ((mepCurve as Duct).get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM) != null)
				{
					result = (mepCurve as Duct).get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM).AsDouble();
				}
				else
				{
					result = (mepCurve as Duct).get_Parameter(BuiltInParameter.RBS_CURVE_DIAMETER_PARAM).AsDouble();
				}
			}
			else if (mepCurve is Pipe)
			{
				result = (mepCurve as Pipe).get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).AsDouble();
			}
			else if (mepCurve is CableTray)
			{
				result = (mepCurve as CableTray).Height;
			}
			else if (mepCurve is Conduit)
			{
				result = (mepCurve as Conduit).get_Parameter(BuiltInParameter.RBS_CONDUIT_DIAMETER_PARAM).AsDouble();
			}
			return result;
		}

		public static double GetWidthOrDiameter(MEPCurve mepCurve)
		{
			double result = 0.0;
			if (mepCurve is Duct)
			{
				if ((mepCurve as Duct).get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM) != null)
				{
					result = (mepCurve as Duct).get_Parameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM).AsDouble();
				}
				else
				{
					result = (mepCurve as Duct).get_Parameter(BuiltInParameter.RBS_CURVE_DIAMETER_PARAM).AsDouble();
				}
			}
			else if (mepCurve is Pipe)
			{
				result = (mepCurve as Pipe).get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).AsDouble();
			}
			else if (mepCurve is CableTray)
			{
				result = (mepCurve as CableTray).Width;
			}
			else if (mepCurve is Conduit)
			{
				result = (mepCurve as Conduit).get_Parameter(BuiltInParameter.RBS_CONDUIT_DIAMETER_PARAM).AsDouble();
			}
			return result;
		}

		public static List<XYZ> GetListXYZ(CableTrayConduitBase cableTray, MEPCurve refCableTray, double space)
		{
			List<XYZ> result = new List<XYZ>();
			YJKLine hyline = new YJKLine(new HYCableTray<CableTrayConduitBase>(cableTray).GetLocationCurve() as Line);
			Line curve = (refCableTray.Location as LocationCurve).Curve as Line;
			XYZ hyendPoint = curve.GetEndPoint(0);
			XYZ hyendPoint2 = curve.GetEndPoint(1);
			XYZ xyz;
			if (Math.Abs(hyline.StartPoint.Z - hyendPoint.Z) < 0.001 && Math.Abs(hyline.StartPoint.Z - hyendPoint2.Z) < 0.001)
			{
				xyz = hyline.IntersectionPoint(Line.CreateBound(new XYZ(hyendPoint.X, hyendPoint.Y, hyline.StartPoint.Z), new XYZ(hyendPoint2.X, hyendPoint2.Y, hyline.StartPoint.Z)));
			}
			else
			{
				xyz = hyline.GetProject(hyendPoint);
			}
			if (xyz != null)
			{
				result = hyline.GetLineXYZList(xyz, space / 2.0);
			}
			return result;
		}

		public static bool IsElementIntersectsElement(Element elem1, Element elem2)
		{
			return new ElementIntersectsElementFilter(elem1).PassesFilter(elem2);
		}
	}
}
